package com.imooc.zhangxiaoxi.stream;

import com.alibaba.fastjson.JSON;
import com.imooc.zhangxiaoxi.lambda.cart.CartService;
import com.imooc.zhangxiaoxi.lambda.cart.Sku;
import com.imooc.zhangxiaoxi.lambda.cart.SkuCategoryEnum;
import org.junit.Before;
import org.junit.Test;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description : 演示流的各种操作
 * @Author : YTY
 * @Date : 2021-01-16 17:09
 */
public class StreamOperator {

    List<Sku> list;

    @Before
    public void init() {
        list = CartService.getCartSkuList();
    }


    /**
     * filter使用：过滤掉不符合断言判断的数据
     */
    @Test
    public void filterTest() {

        System.out.println(list.stream()
                .filter(sku -> SkuCategoryEnum.BOOKS.equals(sku.getSkuCategory()))
                //                .forEach(item ->
                //                        System.out.println(
                //                                JSON.toJSONString(
                //                                        item, true)));
                .map(Sku::getSkuName)
                .collect(Collectors.toList()));
    }

    /**
     * map使用：将一个元素转换成另一个元素
     */
    @Test
    public void mapTest() {
        list.stream()

                // map
                .map(Sku::getSkuName)

                .forEach(System.out::println);
    }

    /**
     * flatMap使用：将一个对象转换成流
     */
    @Test
    public void flatMapTest() {
        list.stream()

                // flatMap
                .flatMap(sku -> Arrays.stream(
                        sku.getSkuName().split("")))

                .forEach(item ->
                        System.out.println(
                                JSON.toJSONString(
                                        item, true)));
    }

    /**
     * peek使用：对流中元素进行遍历操作，与forEach类似，但不会销毁流元素
     */
    @Test
    public void peek() {
        list.stream()

                // peek
                .peek(sku -> System.out.println(sku.getSkuName()))

                .forEach(item ->
                        System.out.println(
                                JSON.toJSONString(
                                        item, true)));
    }

    /**
     * sort使用：对流中元素进行排序，可选则自然排序或指定排序规则。有状态操作
     */
    @Test
    public void sortTest() {
        list.stream()

                .peek(sku -> System.out.println(sku.getSkuName()))

                //sort
                .sorted(Comparator.comparing(Sku::getTotalPrice)
                        .reversed()
                        .thenComparing(Sku::getSkuId)
                )

                .forEach(item ->
                        System.out.println(
                                JSON.toJSONString(
                                        item, true)));
    }

    /**
     * distinct使用：对流元素进行去重。有状态操作
     */
    @Test
    public void distinctTest() {

        list.stream()
                // 转换
                .map(Sku::getSkuCategory)
                // 去重
                .distinct()
                // 遍历
                .forEach(System.out::println);
    }

    /**
     * skip使用：跳过前N条记录。有状态操作
     */
    @Test
    public void skipTest() {

        list.stream()

                // 排序
                .sorted(Comparator.comparing(Sku::getTotalPrice).reversed())
                // 跳过
                .skip(3)
                // 取名
                .map(Sku::getSkuName)
                // 遍历
                .forEach(System.out::println);
    }

    /**
     * limit使用：截断前N条记录。有状态操作
     */
    @Test
    public void limitTest() {
        System.out.println(list.stream()
                .sorted(Comparator.comparing(Sku::getTotalPrice).reversed())

                .skip(3 * 1)

                // limit
                .limit(2)

                // 取名
                .map(Sku::getSkuName)

                // FindFirst
                .findFirst().get());

//                .forEach(item ->
//                        System.out.println(
//                                JSON.toJSONString(
//                                        item, true)));
    }

    /**
     * 问答区：乃好需求Test
     */
    @Test
    public void naiHaoTest() {

        list.stream()
                // 价格升序
                .sorted(Comparator.comparing(Sku::getTotalPrice).reversed())
                // 显示名称和价格
                .map(sku -> sku.getSkuName() + "," + sku.getTotalPrice())
                // 循环输出
                .forEach(System.out::println);
    }

    /**
     * allMatch使用：终端操作，短路操作。所有元素匹配，返回true
     */
    @Test
    public void allMatchTest() {

        System.out.println(list.stream()

                // 遍历，非终端操作
                .peek(sku -> System.out.println(sku.getSkuName()))
                // allMatch
                .allMatch(sku -> sku.getTotalPrice() > 1000));

    }

    /**
     * anyMatch使用：任何元素匹配，返回true
     */
    @Test
    public void anyMatchTest() {

        System.out.println(list.stream()
                // 非终端遍历
                .peek(sku -> System.out.println(sku.getSkuName()))
                // anyMatch
                .anyMatch(sku -> sku.getTotalPrice() > 1000));
    }

    /**
     * noneMatch使用：任何元素都不匹配，返回true
     */
    @Test
    public void noneMatchTest() {

        System.out.println(list.stream()
                // 非终端遍历
                .peek(sku -> System.out.println(sku.getSkuName()))
                // noneMatch
                .noneMatch(sku -> sku.getTotalPrice() > 6666));

    }

    /**
     * 找到第一个
     */
    @Test
    public void findFirstTest() {

        Optional<Sku> optional = list.stream()
                // 非终端遍历
                .peek(sku -> System.out.println(sku.getSkuName()))
                // findFirst
                .findFirst();

        System.out.println(
                JSON.toJSONString(optional.get(), true));
    }

    /**
     * 找任意一个
     */
    @Test
    public void findAnyTest() {

        Optional<Sku> optional = list.stream()
                // peek
                .peek(sku -> System.out.println(sku.getSkuName()))
                // findAny
                .findAny();

        System.out.println(
                JSON.toJSONString(optional.get(), true));
    }

    /**
     * max使用：
     */
    @Test
    public void maxTest() {

        System.out.println(list.stream()
                //获取总价
                .mapToDouble(Sku::getTotalPrice)
                // 最大值
                .max()
                // 取值
                .getAsDouble());
    }

    /**
     * min使用
     */
    @Test
    public void minTest() {

        System.out.println(list.stream()
                .mapToDouble(Sku::getTotalPrice)
                .min()
                .getAsDouble());
    }

    /**
     * count使用：数量大于1的个数
     */
    @Test
    public void countTest() {

        System.out.println(list.stream()
                // 转个数
                .map(Sku::getTotalNum)
                // 大于1
                .filter(number -> number > 1)
                // 个数
                .count());
    }

}
